package com.jinliang.thinkinredis.config;


import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.context.annotation.Lazy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;

//@Aspect
//@Component
public class RedissionLockAspect {
    @Resource
    private RedissonClient redissonClient;

    /**
     * 环绕通知：灵活自由的在目标方法中切入代码
     */
    @Around("@annotation(redissionLock)")
    public Object around(ProceedingJoinPoint joinPoint, RedissionLock redissionLock) throws Throwable {
        // 获取目标方法的名称
        String methodName = joinPoint.getSignature().getName();
        // 获取方法传入参数
        Object[] params = joinPoint.getArgs();
        System.out.println("==@Around== lingyejun blog logger --》 method name " + methodName + " args " + params[0]);
        RLock lock = redissonClient.getLock(params[redissionLock.lockIndexParam()-1].toString());
        boolean b = lock.tryLock(redissionLock.waitTime(), redissionLock.leaseTime(), TimeUnit.MINUTES);
        if (b) {
            lock.unlock();
            return joinPoint.proceed();
        } else {
            return null;
        }

    }

    /**
     * 获取方法中声明的注解
     *
     * @param joinPoint
     * @return
     * @throws NoSuchMethodException
     */
    public RedissionLock getDeclaredAnnotation(ProceedingJoinPoint joinPoint) throws NoSuchMethodException {
        // 获取方法名
        String methodName = joinPoint.getSignature().getName();
        // 反射获取目标类
        Class<?> targetClass = joinPoint.getTarget().getClass();
        // 拿到方法对应的参数类型
        Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
        // 根据类、方法、参数类型（重载）获取到方法的具体信息
        Method objMethod = targetClass.getMethod(methodName, parameterTypes);
        // 拿到方法定义的注解信息
        RedissionLock annotation = objMethod.getDeclaredAnnotation(RedissionLock.class);
        // 返回
        return annotation;
    }

}
